#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "buffer.h"
#include "user.h"
bool Buffer::add(char *buf,int buf_len)
{
    int free_size = 0;
    char *buf_pre = buf;
    if(buf == NULL)
    {
        printf("in write_buf: buf is NULL\n");
        return false;
    }
    if(buf_len > buffer_size)//待写入数据长度超过缓冲区大小
    {
        goto Not_enough;
    }
    /**************计算缓冲区剩余容积*****************/
    if(write_index == read_index)//缓冲区为空
    {
        free_size = buffer_size;
    }
    else if((write_index - read_index) > 0)
    {
        free_size = buffer_size - (write_index - read_index);
    }
    else
    {
        free_size = buffer_size - (write_index + buffer_size - read_index);
    }
    if(buf_len > free_size)
    {
        goto Not_enough;
    }

    if(buf_len <= (buffer_size - write_index))//无需发生翻转
    {
        memcpy(&(data[write_index]),buf_pre,buf_len);//写入数据
    }
    else
    {
        memcpy(&(data[write_index]),buf_pre,
               (buffer_size - write_index));//先将剩余的空间写满

        buf_pre += buffer_size - write_index;//找到新的待写入位置
        memcpy(&(data[0]),buf_pre,
           (buf_len - (buffer_size - write_index)));//再从头开始写完剩余数据
    }
    write_index += buf_len;
    write_index %= buffer_size;
    return true;

    Not_enough:
        /**整个缓冲区都被写满了，说明缓冲区太小
        此处为以后进行缓冲区扩容操作提供接口，本版本不考虑缓冲区扩容。
        ***/
        printf("int write_buf(): The space is insufficient \n");
    return false;
}



/*
读缓冲区，并将读出的数据从缓冲区“删除”（读指针后移）
Input:
　　　　　　　buf　　将读取到的数据写入其中
　　　　　　　read_len　想要读取的长度
Output:
      成功读取 ０　失败 -1
*/
bool Buffer::read(char *buf,int read_len)
{
    int data_len = 0;   //缓冲区中已有的数据的长度
    char *buf_pre = buf;
    if(data == NULL)
    {
        printf("in read_buf: data is NULL\n");
        return false;
    }
    if(buf == NULL)
    {
        printf("in read_buf: buf is NULL\n");
        return false;
    }
    if(read_index == write_index)//缓冲区为空
    {
        goto Not_enough;
    }
     /**************计算缓冲区中已有数据的长度*****************/
    if((write_index - read_index) > 0)
    {
        data_len = write_index - read_index;
    }
    else
    {
        data_len = write_index + buffer_size - read_index;
    }
    if(data_len < read_len)//已有数据长度小于所要读的数据长度
    {
        goto Not_enough;
    }
    if(read_len <= (buffer_size - read_index))//无需发生翻转
    {
        memcpy(buf_pre,&(data[read_index]),read_len);//写入数据
    }
    else
    {
        memcpy(buf_pre,&(data[read_index]),
               (buffer_size - read_index));//先读出未翻转的数据写入buf

        buf_pre += buffer_size - read_index;//找到新的待写入位置
        memcpy(buf_pre,&(data[0]),
           (read_len - (buffer_size - read_index)));//再从头开始读完剩余数据
    }
    read_index += read_len;
    read_index %= buffer_size;
    return true;

    Not_enough:
    return false;
}


/*
查看缓冲区，只拷贝出缓冲区中的相应数据，但是不将该部分数据从缓冲区删除
用于解包操作时查看缓冲区中的数据是否够一个帧头的长度
Input:
　　　　　　　buf　　将读取到的数据写入其中
　　　　　　　read_len　想要读取的长度
Output:
      成功读取 ０　失败 -1
*/
bool Buffer::look(char *buf,int read_len)
{
    int data_len = 0;   //缓冲区中已有的数据的长度
    char *buf_pre = buf;
    if(data == NULL)
    {
        printf("in look_buf: data is NULL\n");
        return false;
    }
    if(buf == NULL)
    {
        printf("in look_buf: buf is NULL\n");
        return false;
    }
    if(read_index == write_index)//缓冲区为空
    {
        goto Not_enough;
    }
     /**************计算缓冲区中已有数据的长度*****************/
    if((write_index - read_index) > 0)
    {
        data_len = write_index - read_index;
    }
    else
    {
        data_len = write_index + buffer_size - read_index;
    }
    if(data_len < read_len)//已有数据长度小于所要读的数据长度
    {
        goto Not_enough;
    }
    if(read_len <= (buffer_size - read_index))//无需发生翻转
    {
        memcpy(buf_pre,&(data[read_index]),read_len);//写入数据
    }
    else
    {
        memcpy(buf_pre,&(data[read_index]),
               (buffer_size - read_index));//先读出未翻转的数据写入buf

        buf_pre += buffer_size - read_index;//找到新的待写入位置
        memcpy(buf_pre,&(data[0]),
           (read_len - (buffer_size - read_index)));//再从头开始读完剩余数据
    }
    return true;

    Not_enough:
    return false;
}


char *Buffer::getframe(char *data_buf)
{
    int framesize = 0;//数据长度
    char *realdata_p = NULL;
    if(data == NULL)
    {
        printf("err:in Buffer::getframe(): data is NULL");
        return NULL;
    }
    if(look(data_buf,FRAMEHEAD_SIZE) == 0)//缓冲区已有数据长度够一帧的帧头
    {
        data_buf[FRAMEHEAD_SIZE] = '\0';            //手动填充'\0',便于字符串操作
        if(data_buf[0] == '$' && data_buf[1] == '&')//帧头校验
        {
            framesize = atoi(&(data_buf[2]));
            printf("framesize: %d\n",framesize);
            framesize += FRAMEHEAD_SIZE;
            if(framesize > MAX_MSGLEN || framesize < 0)
            {
                printf("in decode E1: framehead err\n");
            }
        }
        else
        {

        }
        if(read(data_buf,framesize) == 0)//成功读取回一帧数据
        {
            if(data_buf[framesize - 1] == '#')//帧尾校验
            {
                data_buf[framesize - 1] = '\0';//将帧尾替换成字符串结束标志
                realdata_p = &(data_buf[FRAMEHEAD_SIZE]);//去掉帧头后剩下的即为有效数据
                #ifdef DEBUG_DEDCODE
                printf("decode data： %s \n",realdata_p);
                #endif
                return realdata_p;
            }
            else
            {
                printf("in decode E２: cont find frame end flag\n");
                data_buf[framesize - 1] = '\0';
                printf("ERR data %s\n",data_buf);
            }
        }
    }
    return NULL;
}
